home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / src / history.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  19.8 KB  |  622 lines

  1. // MDF - PORT FROM NCSA VERSION 2.1
  2.  
  3. /****************************************************************************
  4.  * NCSA Mosaic for the X Window System                                      *
  5.  * Software Development Group                                               *
  6.  * National Center for Supercomputing Applications                          *
  7.  * University of Illinois at Urbana-Champaign                               *
  8.  * 605 E. Springfield, Champaign IL 61820                                   *
  9.  * mosaic@ncsa.uiuc.edu                                                     *
  10.  *                                                                          *
  11.  * Copyright (C) 1993, Board of Trustees of the University of Illinois      *
  12.  *                                                                          *
  13.  * NCSA Mosaic software, both binary and source (hereafter, Software) is    *
  14.  * copyrighted by The Board of Trustees of the University of Illinois       *
  15.  * (UI), and ownership remains with the UI.                                 *
  16.  *                                                                          *
  17.  * The UI grants you (hereafter, Licensee) a license to use the Software    *
  18.  * for academic, research and internal business purposes only, without a    *
  19.  * fee.  Licensee may distribute the binary and source code (if released)   *
  20.  * to third parties provided that the copyright notice and this statement   *
  21.  * appears on all copies and that no charge is associated with such         *
  22.  * copies.                                                                  *
  23.  *                                                                          *
  24.  * Licensee may make derivative works.  However, if Licensee distributes    *
  25.  * any derivative work based on or derived from the Software, then          *
  26.  * Licensee will (1) notify NCSA regarding its distribution of the          *
  27.  * derivative work, and (2) clearly notify users that such derivative       *
  28.  * work is a modified version and not the original NCSA Mosaic              *
  29.  * distributed by the UI.                                                   *
  30.  *                                                                          *
  31.  * Any Licensee wishing to make commercial use of the Software should       *
  32.  * contact the UI, c/o NCSA, to negotiate an appropriate license for such   *
  33.  * commercial use.  Commercial use includes (1) integration of all or       *
  34.  * part of the source code into a product for sale or license by or on      *
  35.  * behalf of Licensee to third parties, or (2) distribution of the binary   *
  36.  * code or source code to third parties that need it to utilize a           *
  37.  * commercial product sold or licensed by or on behalf of Licensee.         *
  38.  *                                                                          *
  39.  * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR   *
  40.  * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED          *
  41.  * WARRANTY.  THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE    *
  42.  * USERS OF THIS SOFTWARE.                                                  *
  43.  *                                                                          *
  44.  * By using or copying this Software, Licensee agrees to abide by the       *
  45.  * copyright law and all other applicable laws of the U.S. including, but   *
  46.  * not limited to, export control laws, and the terms of this license.      *
  47.  * UI shall have the right to terminate this license immediately by         *
  48.  * written notice upon Licensee's breach of, or non-compliance with, any    *
  49.  * of its terms.  Licensee may be held legally responsible for any          *
  50.  * copyright infringement that is caused or encouraged by Licensee's        *
  51.  * failure to abide by the terms of this license.                           *
  52.  *                                                                          *
  53.  * Comments and questions are welcome and can be sent to                    *
  54.  * mosaic-x@ncsa.uiuc.edu.                                                  *
  55.  ****************************************************************************/
  56.  
  57. #include "includes.h"
  58. #include "HTML.h"
  59. #include "mosaic.h"
  60. #include "globals.h"
  61. #include "htmlgad.h"
  62. #include "gui.h"
  63. #include "XtoI.h"
  64. #include "protos.h"
  65.  
  66. extern ULONG HookEntry();
  67.  
  68. /* ------------------------------------------------------------------------ */
  69. /* ----------------------------- HISTORY LIST ----------------------------- */
  70. /* ------------------------------------------------------------------------ */
  71.  
  72. /* ---------------------------- kill functions ---------------------------- */
  73.  
  74. /* Free the data contained in an mo_node.  Currently we only free
  75.    the text itself. */
  76. mo_status mo_free_node_data (mo_node *node)
  77. {
  78.   if (node->texthead != NULL)
  79.     {
  80.       free (node->texthead);
  81.       node->texthead = NULL;
  82.     }
  83.   if (node->title != NULL)
  84.     {
  85.       free (node->title);
  86.       node->title = NULL;
  87.     }
  88. #if 0
  89.   /* Leads to memory getting freed twice in some cases, apparently.
  90.      Not sure why. */
  91.   if (node->url != NULL)
  92.     free (node->url);
  93. #endif
  94.   if (node->ref != NULL)
  95.     {
  96.       free (node->ref);
  97.       node->ref = NULL;
  98.     }
  99.  
  100.   if (node->cached_stuff)
  101.     {
  102. //      HTMLFreeWidgetInfo (node->cached_stuff);
  103.       node->cached_stuff = NULL;
  104.     }
  105.  
  106.   return mo_succeed;
  107. }
  108.  
  109. /* Kill a single mo_node associated with a given mo_window; it
  110.    the history list exists we delete it from that.  In any case
  111.    we call mo_free_node_data and return. */
  112. mo_status mo_kill_node (mo_window *win, mo_node *node)
  113. {
  114.   if (win->history_list)
  115.     DoMethod(win->history_list, MUIM_List_Remove, node->position - 1);
  116.  
  117.   mo_free_node_data (node);
  118.  
  119.   return mo_succeed;
  120. }
  121.  
  122. /* Iterate through all descendents of an mo_node, but not the given
  123.    mo_node itself, and kill them.  This is equivalent to calling
  124.    mo_kill_node on each of those nodes, except this is faster since
  125.    all the Motif list entries can be killed at once. */
  126. mo_status mo_kill_node_descendents (mo_window *win, mo_node *node)
  127. {
  128.   mo_node *foo;
  129.   int count = 0;
  130.  
  131.   if (node == NULL)
  132.     return mo_fail;
  133.   for (foo = node->next; foo != NULL; foo = foo->next)
  134.     {
  135.       mo_free_node_data (foo);
  136.       count++;
  137.     }
  138.  
  139.   /* Free count number of items from the end of the list... */
  140.   if (win->history_list && count)
  141.     {
  142.       int i;
  143.       for (i=0; i<count; i++)
  144.     DoMethod(win->history_list, MUIM_List_Remove, MUIV_List_Remove_Last);
  145.     }
  146.  
  147.   return mo_succeed;
  148. }
  149.  
  150. /* ------------------------ mo_add_node_to_history ------------------------ */
  151.  
  152. /* Called from mo_record_visit to insert an mo_node into the history
  153.    list of an mo_window. */
  154. mo_status mo_add_node_to_history (mo_window *win, mo_node *node)
  155. {
  156.   /* If there is no current node, this is our first time through. */
  157.   if (win->history == NULL)
  158.     {
  159.       win->history = node;
  160.       node->previous = NULL;
  161.       node->next = NULL;
  162.       node->position = 1;
  163.       win->current_node = node;
  164.     }
  165.   else
  166.     {
  167.       /* Node becomes end of history list. */
  168.       /* Point back at current node. */
  169.       node->previous = win->current_node;
  170.       /* Point forward to nothing. */
  171.       node->next = NULL;
  172.       node->position = node->previous->position + 1;
  173.       /* Kill descendents of current node, since we'll never
  174.          be able to go forward to them again. */
  175.       mo_kill_node_descendents (win, win->current_node);
  176.       /* Current node points forward to this. */
  177.       win->current_node->next = node;
  178.       /* Current node now becomes new node. */
  179.       win->current_node = node;
  180.     }
  181.  
  182.   if (win->history_list){
  183.         DoMethod(win->history_list, MUIM_List_Select, node->previous->position - 1,
  184.             MUIV_List_Select_Off, NULL);
  185.         DoMethod(win->history_list, MUIM_List_Insert, &(node->title), 1,
  186.             MUIV_List_Insert_Bottom);
  187.         DoMethod(win->history_list, MUIM_List_Select, node->position - 1,
  188.             MUIV_List_Select_On, NULL);
  189.         }
  190.  
  191.   return mo_succeed;
  192. }
  193.  
  194. /* ---------------------------- mo_grok_title ----------------------------- */
  195.  
  196. /* Make up an appropriate title for a document that does not otherwise
  197.    have one associated with it. */
  198. char *mo_grok_alternate_title (char *url, char *ref)
  199. {
  200.   char *title, *foo1, *foo2;
  201.  
  202.   if (!strncmp (url, "gopher:", 7))
  203.     {
  204.       /* It's a gopher server. */
  205.       /* Do we have a ref? */
  206.       if (ref)
  207.         {
  208.           char *tmp = ref;
  209.           while (*tmp && (*tmp == ' ' || *tmp == '\t'))
  210.             tmp++;
  211.           title = strdup (tmp);
  212.           goto done;
  213.         }
  214.       else
  215.         {
  216.           /* Nope, no ref.  Make up a title. */
  217.           foo1 = url + 9;
  218.           foo2 = strstr (foo1, ":");
  219.           /* If there's a trailing colon (always should be.. ??)... */
  220.           if (foo2)
  221.             {
  222.               char *server = (char *) malloc ((foo2 - foo1 + 2));
  223.               
  224.               bcopy (foo1, server, (foo2 - foo1));
  225.               server[(foo2 - foo1)] = '\0';
  226.               
  227.               title = (char *) malloc ((strlen (server) + 32) * sizeof (char));
  228.               sprintf (title, "Gopher server at %s\0", server);
  229.               
  230.               /* OK, we got a title... */
  231.               free (server);
  232.  
  233.               goto done;
  234.             }
  235.           else
  236.             {
  237.               /* Aw hell... */
  238.               title = strdup ("Gopher server");
  239.               goto done;
  240.             }
  241.         }
  242.     }
  243.  
  244.   /* If we got here, assume we should use 'ref' if possible
  245.      for the WAIS title. */
  246.   if (!strncmp (url, "wais:", 5) || 
  247.       !strncmp (url, "http://info.cern.ch:8001/", 25) ||
  248.       !strncmp (url, "http://info.cern.ch.:8001/", 26) ||
  249.       !strncmp (url, "http://www.ncsa.uiuc.edu:8001/", 30))
  250.     {
  251.       /* It's a WAIS server. */
  252.       /* Do we have a ref? */
  253.       if (ref)
  254.         {
  255.           title = strdup (ref);
  256.           goto done;
  257.         }
  258.       else
  259.         {
  260.           /* Nope, no ref.  Make up a title. */
  261.           foo1 = url + 7;
  262.           foo2 = strstr (foo1, ":");
  263.           /* If there's a trailing colon (always should be.. ??)... */
  264.           if (foo2)
  265.             {
  266.               char *server = (char *) malloc ((foo2 - foo1 + 2));
  267.               
  268.               bcopy (foo1, server, (foo2 - foo1));
  269.               server[(foo2 - foo1)] = '\0';
  270.               
  271.               title = (char *) malloc ((strlen (server) + 32) * sizeof (char));
  272.               sprintf (title, "WAIS server at %s\0", server);
  273.               
  274.               /* OK, we got a title... */
  275.               free (server);
  276.  
  277.               goto done;
  278.             }
  279.           else
  280.             {
  281.               /* Aw hell... */
  282.               title = strdup ("WAIS server");
  283.               goto done;
  284.             }
  285.         }
  286.     }
  287.  
  288.   if (!strncmp (url, "news:", 5))
  289.     {
  290.       /* It's a news source. */
  291.       if (strstr (url, "@"))
  292.         {
  293.           /* It's a news article. */
  294.           foo1 = url + 5;
  295.           
  296.           title = (char *)malloc ((strlen (foo1) + 32) * sizeof (char));
  297.           sprintf (title, "USENET article %s\0", foo1);
  298.  
  299.           goto done;
  300.         }
  301.       else
  302.         {
  303.           /* It's a newsgroup. */
  304.           foo1 = url + 5;
  305.           
  306.           title = (char *)malloc ((strlen (foo1) + 32) * sizeof (char));
  307.           sprintf (title, "USENET newsgroup %s\0", foo1);
  308.  
  309.           goto done;
  310.         }
  311.     }
  312.  
  313.   if (!strncmp (url, "file:", 5))
  314.     {
  315.       /* It's a file. */
  316.       if (strncmp (url, "file:///", 8) == 0)
  317.         {
  318.           /* It's a local file. */
  319.           foo1 = url + 7;
  320.           
  321.           title = (char *)malloc ((strlen (foo1) + 32) * sizeof (char));
  322.           sprintf (title, "Local file %s\0", foo1);
  323.           
  324.           goto done;
  325.         }
  326.       else if (strncmp (url, "file://localhost/", 17) == 0)
  327.         {
  328.           /* It's a local file. */
  329.           foo1 = url + 16;
  330.           
  331.           title = (char *)malloc ((strlen (foo1) + 32) * sizeof (char));
  332.           sprintf (title, "Local file %s\0", foo1);
  333.           
  334.           goto done;
  335.         }
  336.       else
  337.         {
  338.           /* It's a remote file. */
  339.           foo1 = url + 7;
  340.           
  341.           title = (char *)malloc ((strlen (foo1) + 32) * sizeof (char));
  342.           sprintf (title, "Remote file %s\0", foo1);
  343.           
  344.           goto done;
  345.         }
  346.     }
  347.   
  348.   if (!strncmp (url, "ftp:", 4))
  349.     {
  350.       {
  351.         /* It's a remote file. */
  352.         foo1 = url + 6;
  353.         
  354.         title = (char *)malloc ((strlen (foo1) + 32) * sizeof (char));
  355.         sprintf (title, "Remote file %s\0", foo1);
  356.         
  357.         goto done;
  358.       }
  359.     }
  360.   
  361.   /* Punt... */
  362.   title = (char *) malloc ((strlen (url) + 24) * sizeof (char));
  363.   sprintf (title, "Untitled, URL %s\0", url);
  364.   
  365.  done:
  366.   return title;
  367. }
  368.  
  369. /* Figure out a title for the given URL.  'ref', if it exists,
  370.    was the text used for the anchor that pointed us to this URL;
  371.    it is not required to exist. */
  372. char *mo_grok_title (mo_window *win, char *url, char *ref)
  373. {
  374.   char *title = NULL, *t;
  375.  
  376. #ifdef _AMIGA
  377.   get(HTML_Gad, HTMLA_title, (ULONG *)(&title));
  378. #else
  379.   XtVaGetValues (win->scrolled_win, WbNtitleText, &title, NULL);
  380. #endif /* _AMIGA */
  381.  
  382.   if (!title)
  383.     t = mo_grok_alternate_title (url, ref);
  384.   else if (!strcmp (title, "Document"))
  385.     t = mo_grok_alternate_title (url, ref);
  386.   else
  387.     {
  388.       char *tmp = title;
  389.       while (*tmp && (*tmp == ' ' || *tmp == '\t'))
  390.         tmp++;
  391.       if (*tmp)
  392.         t = strdup (tmp);
  393.       else
  394.         t = mo_grok_alternate_title (url, ref);
  395.     }
  396.  
  397.   mo_convert_newlines_to_spaces (t);
  398.  
  399.   return t;
  400. }
  401.  
  402. /* --------------------------- mo_record_visit ---------------------------- */
  403.  
  404. /* Called when we visit a new node (as opposed to backing up or
  405.    going forward).  Create an mo_node entry, call mo_grok_title
  406.    to figure out what the title is, and call mo_node_to_history
  407.    to add the new mo_node to both the window's data structures and
  408.    to its Motif history list. */
  409. mo_status mo_record_visit (mo_window *win, char *url, char *newtext, 
  410.                            char *newtexthead, char *ref)
  411. {
  412.   mo_node *node = (mo_node *)malloc (sizeof (mo_node));
  413.   node->url = url;
  414.   node->text = newtext;
  415.   node->texthead = newtexthead;
  416.   node->ref = ref;
  417.   /* Figure out what the title is... */
  418.   node->title = mo_grok_title (win, url, ref);
  419.   
  420.   /* This will be recalc'd when we leave this node. */
  421.   node->docid = 1;
  422.   node->cached_stuff = NULL;
  423.  
  424.   mo_add_node_to_history (win, node);
  425.  
  426.   return mo_succeed;
  427. }
  428.  
  429. /* ------------------------- navigation functions ------------------------- */
  430.  
  431. /* Back up a node. */
  432. mo_status mo_back_node (mo_window *win)
  433. {
  434.   /* If there is no previous node, choke. */
  435.   if (!win->current_node || win->current_node->previous == NULL)
  436.     return mo_fail;
  437.  
  438.   mo_set_win_current_node (win, win->current_node->previous);
  439.  
  440. //  ResetAmigaGadgets();
  441.  
  442.  
  443. #ifndef _AMIGA
  444.   {
  445.     int doc, view, y;
  446.     get(HTML_Gad, HTMLA_view_height, &view);
  447.     get(HTML_Gad, HTMLA_doc_height, &doc);
  448.     get(HTML_Gad, HTMLA_scroll_y, &y);
  449.     set(SB_Vert, MUIA_Prop_Entries, doc);
  450.     set(SB_Vert, MUIA_Prop_Visible, view);
  451.     set(SB_Vert, MUIA_Prop_First, y);
  452.     get(HTML_Gad, HTMLA_view_width, &view);
  453.     get(HTML_Gad, HTMLA_doc_width, &doc);
  454.     set(SB_Horiz, MUIA_Prop_Entries, doc);
  455.     set(SB_Horiz, MUIA_Prop_Visible, view);
  456.     set(SB_Horiz, MUIA_Prop_First, 0);
  457. //  set(LV_Source, MUIA_Floattext_Text, t);
  458.   }
  459. #endif
  460.  
  461.   return mo_succeed;
  462. }
  463.  
  464. /* Go forward a node. */
  465. mo_status mo_forward_node (mo_window *win)
  466. {
  467.   /* If there is no next node, choke. */
  468.   if (!win->current_node || win->current_node->next == NULL)
  469.     return mo_fail;
  470.  
  471.   mo_set_win_current_node (win, win->current_node->next);
  472. //  ResetAmigaGadgets();
  473.  
  474. #ifndef _AMIGA
  475.   {
  476.     int doc, view, y;
  477.     get(HTML_Gad, HTMLA_view_height, &view);
  478.     get(HTML_Gad, HTMLA_doc_height, &doc);
  479.     get(HTML_Gad, HTMLA_scroll_y, &y);
  480.     set(SB_Vert, MUIA_Prop_Entries, doc);
  481.     set(SB_Vert, MUIA_Prop_Visible, view);
  482.     set(SB_Vert, MUIA_Prop_First, y);
  483.     get(HTML_Gad, HTMLA_view_width, &view);
  484.     get(HTML_Gad, HTMLA_doc_width, &doc);
  485.     set(SB_Horiz, MUIA_Prop_Entries, doc);
  486.     set(SB_Horiz, MUIA_Prop_Visible, view);
  487.     set(SB_Horiz, MUIA_Prop_First, 0);
  488. //  set(LV_Source, MUIA_Floattext_Text, t);
  489.   }
  490. #endif
  491.  
  492.   return mo_succeed;
  493. }
  494.  
  495. /* Visit an arbitrary position.  This is called when a history
  496.    list entry is double-clicked upon.
  497.  
  498.    Iterate through the window history; find the mo_node associated
  499.    with the given position.  Call mo_set_win_current_node. */
  500. mo_status mo_visit_position (mo_window *win, int pos)
  501. {
  502.   mo_node *node;
  503.   
  504.   for (node = win->history; node != NULL; node = node->next)
  505.     {
  506.       if (node->position == pos)
  507.         {
  508.           mo_set_win_current_node (win, node);
  509.           goto done;
  510.         }
  511.     }
  512.  
  513.   fprintf (stderr, "UH OH BOSS, asked for position %d, ain't got it.\n",
  514.            pos);
  515.  
  516.  done:
  517.   return mo_succeed;
  518. }
  519.  
  520. /* ---------------------------- misc functions ---------------------------- */
  521.  
  522. mo_status mo_dump_history (mo_window *win)
  523. {
  524.   mo_node *node;
  525.   fprintf (stderr, "----------------- history -------------- \n");
  526.   fprintf (stderr, "HISTORY is 0x%08x\n", win->history);
  527.   for (node = win->history; node != NULL; node = node->next)
  528.     {
  529.       fprintf (stderr, "NODE %d %s\n", node->position, node->url);
  530.       fprintf (stderr, "     TITLE %s\n", node->title);
  531.     }
  532.   fprintf (stderr, "CURRENT NODE %d %s\n", win->current_node->position,
  533.            win->current_node->url);
  534.   fprintf (stderr, "----------------- history -------------- \n");
  535.   return mo_succeed;
  536. }  
  537.  
  538. /* ------------------------------------------------------------------------ */
  539. /* ----------------------------- HISTORY GUI ------------------------------ */
  540. /* ------------------------------------------------------------------------ */
  541.  
  542. /* We've just init'd a new history list widget; look at the window's
  543.    history and load 'er up. */
  544. void mo_load_history_list (mo_window *win, Object *list)
  545. {
  546.     mo_node *node;
  547.  
  548.     DoMethod(list, MUIM_List_Clear);
  549.     for (node = win->history; node != NULL; node = node->next){
  550.         DoMethod(list, MUIM_List_Insert, &(node->title), 1,
  551.             MUIV_List_Insert_Bottom);
  552.         }
  553.   
  554.     DoMethod(list, MUIM_List_Select, win->current_node->position - 1,
  555.         MUIV_List_Select_On, NULL);
  556. }
  557.  
  558. /* stuff about mailing the history file... */
  559.  
  560. /* ---------------------------- history_win_cb ---------------------------- */
  561.  
  562. static unsigned long history_list_cb(struct Hook *h, void *o, void *msg)
  563. {
  564.   mo_window *win = (mo_window *)h->h_Data;
  565.   Object *list = (Object *)o;
  566.   int x;
  567.  
  568.   get(list, MUIA_List_Active, &x);
  569.   mo_visit_position (win, x+1);
  570.  
  571.   return (unsigned long)0;
  572. }
  573.  
  574.  
  575. mo_status mo_post_history_win (mo_window *win)
  576. {
  577.   if (!win->history_win)
  578.     {
  579.       struct Hook *history_list_cb_hook = malloc(sizeof(struct Hook));
  580.  
  581.       history_list_cb_hook->h_Entry = HookEntry;
  582.       history_list_cb_hook->h_SubEntry = history_list_cb;
  583.       history_list_cb_hook->h_Data = win;
  584.       
  585.       /* Create it for the first time. */
  586.       win->history_win = WindowObject,
  587.         MUIA_Window_Title, "Window History",
  588.         MUIA_Window_ID, MAKE_ID('H','S','T','Y'),
  589.         MUIA_Window_RefWindow, win->view,
  590. //rs        MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  591. //rs        MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  592. //rs        MUIA_Window_Width, 300,
  593. //rs        MUIA_Window_Height, 150,
  594.         WindowContents, VGroup,
  595.           Child, win->history_list = ListviewObject,
  596.             MUIA_Listview_DoubleClick, TRUE,
  597.             MUIA_Listview_List, ListObject,
  598.               InputListFrame,
  599.               MUIA_List_ConstructHook, MUIV_List_ConstructHook_String,
  600.               MUIA_List_DestructHook,  MUIV_List_DestructHook_String,
  601.             End,
  602.           End,
  603.         End,
  604.       End;
  605.  
  606.         DoMethod(win->history_win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  607.             win->history_win, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  608.  
  609.         DoMethod(win->history_list, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
  610.             win->history_list, 2, MUIM_CallHook, history_list_cb_hook);
  611.  
  612.         DoMethod(App, OM_ADDMEMBER, win->history_win);
  613.  
  614.         /* Go get the history up to this point set up... */
  615.            mo_load_history_list (win, win->history_list);
  616.         }
  617.   
  618.   set(win->history_win, MUIA_Window_Open, TRUE);
  619.   
  620.   return mo_succeed;
  621. }
  622.